#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "aimage.h"
#include "aimage_utils.h"
#include "aimage_ppm.h"

#define BUFSIZE  256

class ALIGN_FRAME
{
	public:
	char filename[ BUFSIZE ];
	float offset_from_origin_x;
	float offset_from_origin_y;
};

class ALIGN_FRAMES
{
	public:

	ALIGN_FRAMES( void ) 
	{
		dir_found = false;
		frames_found = false;
		dim_found = false;
	}

	bool dir_found;
	bool frames_found;
	bool dim_found;

	char dirname[ BUFSIZE ];
	int num_frames;
	ALIGN_FRAME *frames;
	int x_dim;
	int y_dim;
};

int main( int argc, const char *argv[] )
{
	FILE *f;
	char buffer[  BUFSIZE  ];
	int xoffset = 0;
	int yoffset = 0;

	if ( argc != 3 )
	{
		fprintf(stderr, "%s align_file.txt images.txt", argv[ 0 ]);
	}

	SOLAR_FRAMES_ALIGNMENT align_data;
	align_data.read_solar_align_data( argv[1] );

	ALIGN_FRAMES align_frames;

	int frames_read = 0;
	f = fopen( argv[ 2 ], "rt" );
	assert( f );
	while ( fgets( buffer, BUFSIZE, f ) != NULL )
	{
		char command[ BUFSIZE ];
		char *c;
		char *rest = NULL;
	
		strcpy( command, buffer );
	
		for ( c = command; *c; c++ )
		{
			if ( *c == ' ' )
			{
				*c = 0;
				rest = c+1;
				break;
			}
		}

		if ( rest == NULL )
		{
			continue;
		}

		if ( strcmp( command, "dir" ) == 0 )
		{
			sscanf( rest, "%s", align_frames.dirname );
			align_frames.dir_found = true; 
		}
		if ( strcmp( command, "dim" ) == 0 )
		{
			sscanf( rest, "%d %d", 
					&align_frames.x_dim,
					&align_frames.y_dim );
			align_frames.dim_found = true; 
		}
		if ( strcmp( command, "frames" ) == 0 )
		{
			sscanf( rest, "%d", &align_frames.num_frames );
			align_frames.frames = new ALIGN_FRAME[ align_frames.num_frames ];
			align_frames.frames_found = true; 
		}
		if ( strcmp( command, "frame" ) == 0 )
		{
			assert( align_frames.frames_found );
			assert( frames_read < align_frames.num_frames );
			sscanf( rest, "%s %g %g",
					align_frames.frames[ frames_read ].filename, 
					&(align_frames.frames[ frames_read ].offset_from_origin_x), 
					&(align_frames.frames[ frames_read ].offset_from_origin_y) 
			); 
			frames_read++;
		}
	}

	fprintf(stderr, "Frames expected %d frames read %d\n",
		align_frames.num_frames,
		frames_read );

	assert( frames_read == align_frames.num_frames );
	assert( align_frames.frames_found );
	assert( align_frames.dim_found );
	assert( align_frames.dir_found );

	int iframe;

	AIMAGE stage_img;
	AIMAGE stage_alpha;
	AIMAGE alpha_ref;
	stage_img.alloc_image( align_frames.x_dim, align_frames.y_dim );
	stage_alpha.alloc_image( align_frames.x_dim, align_frames.y_dim );
	int width, height;

	{
		AIMAGE image;
		ALIGN_FRAME *frame = align_frames.frames; 
		AIMAGE_PPM_UTILS::load( image, frame->filename );
		image.get_dim( width, height );
	}

	alpha_ref.alloc_image( width, height );
	AIU::cls( alpha_ref, 1, 1, 1 );

	for ( iframe = 0; iframe < align_frames.num_frames; ++iframe )
	{
		AIMAGE image;
		ALIGN_FRAME *frame = align_frames.frames + iframe; 
		float frame_origin_x, frame_origin_y;
		int img_dst_x0;
		int img_dst_y0;
		int img_dst_x1;
		int img_dst_y1;
		int img_src_x0;
		int img_src_y0;
		int img_src_x1;
		int img_src_y1;
		float x_center, y_center;
		char dfile[ BUFSIZE ];
	
		AIU::cls( stage_img, 0, 0, 0 );
		AIU::cls( stage_alpha, 0, 0, 0 );

		fprintf(stderr, "reading %s\n", frame->filename );
		AIMAGE_PPM_UTILS::load( image, frame->filename );
		
		float rad;
		align_data.lookup_alignment( frame->filename,
			frame_origin_x, frame_origin_y, rad );

		img_dst_x0 = 0;
		img_dst_y0 = 0;
		img_dst_x1 = align_frames.x_dim - 1;
		img_dst_y1 = align_frames.y_dim - 1;
 
		x_center = frame->offset_from_origin_x + frame_origin_x; 
		y_center = frame->offset_from_origin_y + frame_origin_y;

		xoffset += 0;
		yoffset += 0;

		img_src_x0 = x_center + xoffset - align_frames.x_dim / 2;
		img_src_y0 = y_center + xoffset - align_frames.y_dim / 2;

		img_src_x1 = img_src_x0 + align_frames.x_dim -1;
		img_src_y1 = img_src_y0 + align_frames.y_dim -1;

		if ( img_src_x1 < 0 || img_src_y1 < 0 ||
			img_src_x0 >= width  || img_src_y0 >= height )
		{
			img_src_x0 = 0;
			img_src_x1 = 0;
			img_src_y0 = 0;
			img_src_y1 = 0;
			img_dst_x0 = 0;
			img_dst_y0 = 0;
		}
		else
		{
			int adjust;
			if ( img_src_x0 < 0 )
			{
				adjust = -img_src_x0;
				img_src_x0 += adjust;
				img_dst_x0 += adjust;
			}
			if ( img_src_y0 < 0 )
			{
				adjust = -img_src_y0;
				img_src_y0 += adjust;
				img_dst_y0 += adjust;
			}
			if ( img_src_x1 >= width )
			{
				adjust = img_src_x1 - width + 1;
				img_src_x1 -= adjust;
			}
			if ( img_src_y1 >= height )
			{
				adjust = img_src_y1 - height + 1;
				img_src_y1 -= adjust;
			}
		}

		fprintf(stderr, "%g %g (%d %d)->(%d %d)\n", x_center, y_center,
				img_src_x0,
				img_src_y0,
				img_src_x1,
				img_src_y1
		);

		stage_img.copy( image, 
				img_src_x0, img_src_y0, 
				img_src_x1 - img_src_x0 + 1, img_src_y1 - img_src_y0 + 1,
				img_dst_x0, img_dst_y0 );

		stage_alpha.copy( alpha_ref,
				img_src_x0, img_src_y0, 
				img_src_x1 - img_src_x0 + 1, img_src_y1 - img_src_y0 + 1,
				img_dst_x0, img_dst_y0 );

		sprintf( dfile, "%s/%s", align_frames.dirname, frame->filename );  

		AIMAGE_PPM_UTILS::save( stage_img, dfile, false );

		sprintf( dfile, "%s/alpha_%s", align_frames.dirname, frame->filename );
		AIMAGE_PPM_UTILS::save( stage_alpha, dfile, true);
	}
}

